home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d11 / underli2.arc / ISRESDNT.ASM next >
Encoding:
Assembly Source File  |  1988-01-22  |  12.4 KB  |  259 lines

  1.           PAGE   60,132
  2.           TITLE  ISRESDNT.ASM
  3.           PAGE
  4. ;-----------------------------------------------------------------------------
  5. ; SUMMARY
  6. ;-----------------------------------------------------------------------------
  7.  
  8. ;         Near Procedure is_resident.  
  9. ;         Find out if a copy of this program is resident.
  10.  
  11. ;         Input:
  12. ;              SI = OFFSET of the signature (see below)
  13. ;              DI = OFFSET of test string (see below)
  14. ;              AX = number of characters in test string (see below)
  15. ;              DS = DS for calling program*
  16. ;              ES = PSP segment address for the calling program
  17. ;             *The DOS loader sets DS and ES properly in the case of COM
  18. ;         files.  It sets ES properly in the case of EXE files, and the
  19. ;         calling program must set DS before calling this procedure.
  20.  
  21. ;         Output:
  22. ;              AX indicates the result of the procedure:
  23. ;                  =  0 if it does not find a copy already resident
  24. ;                  =  1 if it finds a copy already resident
  25. ;                  = -1 if the DOS major version is not legal
  26. ;       |          = -2 if there is a memory allocation error
  27. ;              CF is set if a copy of this program is resident or if the
  28. ;         DOS version is not legal
  29. ;              DS = DS for the first copy of this program in memory.  Note
  30. ;                   that if no earlier copy is resident, it is DS of the
  31. ;                   calling program.
  32. ;              ES = DS for the calling program.
  33.  
  34. ;              This procedure examines memory which could contain a copy
  35. ;         of itself for a signature, which is a word which is ideally quite
  36. ;         rare in other contexts.  If it finds a match, it then checks
  37. ;         whether the proper memory also matches a test string, which should
  38. ;         positively identify a copy.  If it finds a match, it sets DS to
  39. ;         the DS value for the copy and sets the carry flag.  Otherwise, it
  40. ;         sets DS to the DS value for this copy and unsets the carry flag.
  41. ;         If you haven't changed any of the ASSUME's, a memory reference
  42. ;         with no segment override will refer to the first copy of the pro-
  43. ;         gram, and a memory reference with an ES segment override will refer
  44. ;         to this copy of the program.
  45.  
  46. ;              A good value for the signature would be a word made up of
  47. ;         the first two letters of the program name, OR'ed with 8080H to
  48. ;         avoid all ASCII codes.  The procedure replaces the first two
  49. ;         characters of the test string with the signature to distinguish
  50. ;         between a run copy of the program and a tramp copy.  As a result,
  51. ;         the first word of the test string should be different than the 
  52. ;         signature.  A DW 0 is as good as anything.  The rest of the test
  53. ;         string could be the program name itself.
  54.  
  55. ;              The segment name COMSEG matches COMSKEL.ASM.  If the calling 
  56. ;         program has a different segment name, change it to match.  The
  57. ;         calling program should contain:
  58. ;              EXTRN is_resident:NEAR
  59. ;         inside its COMSKEL (or equivalent) segment.
  60. ;              
  61.  
  62. ;       |      Chris Dunford sent me the following information on 6/16/86:
  63. ;       |      "For each block of allocated memory, DOS maintains a 16-byte
  64. ;       | (one paragraph) block header.  The header is located in the
  65. ;       | paragraph immediately preceding the allocated block. ...
  66. ;       | The form of the header is as follows:
  67. ;       | OFFSET  TYPE  CONTENTS
  68. ;       |   0     Byte  'Z' = this is the last block in the chain
  69. ;       |               'M' = this is not the last block
  70. ;       |               Anything else means that the memory allocation
  71. ;       |               chain has been destroyed (this is the source of
  72. ;       |               DOS's "Memory allocation error" message).
  73. ;       |
  74. ;       |   1     Word  Segment address of Program Segment Prefix of the
  75. ;       |               program that 'owns' this block.  Zero here
  76. ;       |               indicates that the block is unallocated (free).
  77. ;       |
  78. ;       |   3     Word  Size of block in paragraphs (does not include
  79. ;       |               size of header).
  80. ;       |
  81. ;       |      ...
  82. ;       |
  83. ;       |      ... the address of the first header block by using the
  84. ;       | undocumented DOS function 52H.  On return, the word at ES:[BX-2]
  85. ;       | contains the segment at which you should find the first header."
  86.          
  87. ;       |      Since DOS function 52H is undocumented, this procedure may
  88. ;       | not work with Version 1.? or with Version 4.? or later.  I have
  89. ;       | called these values MIN_DOS and MAX_DOS.  If it does work, change
  90. ;       | one or both of them.
  91. ;         Author      : Lew Paper
  92. ;         Date written: 6/10/86
  93. ;         Revisions   : 
  94. ;         6/28/86            Revise to use DOS 2 and 3 memory allocation
  95. ;                       block information.
  96.  
  97. ;-----------------------------------------------------------------------------
  98. ; INITIAL DIRECTIVES
  99. ;-----------------------------------------------------------------------------
  100.  
  101. MIN_DOS   EQU    2
  102. MAX_DOS   EQU    3
  103.  
  104. ;         Synonyms for variables saved on the stack
  105. length_test_string EQU [BP+0]          ; Length of test string
  106. old_DS    EQU    [BP+2]                ; DS from calling program
  107. original_stack_junk EQU   4            ; Number of bytes on stack for
  108.                                        ; variables which will not be
  109.                                        ; restored at all exits.
  110.  
  111. doscall   MACRO
  112.           INT    21h                   ; call MS-DOS function
  113.           ENDM                         ; doscall
  114.  
  115. COMSEG    SEGMENT PARA PUBLIC 'CODE'
  116.           ASSUME CS:COMSEG,DS:COMSEG,ES:COMSEG,SS:COMSEG
  117.  
  118. ;-----------------------------------------------------------------------------
  119.           PUBLIC is_resident
  120. is_resident PROC   NEAR
  121.           PUSH   BX                    ; Save uninitialized registers
  122.           PUSH   CX
  123.           PUSH   DX
  124.           PUSH   BP
  125.           PUSH   ES                    
  126.  
  127.           PUSH   DS                    ; Synonym old_DS
  128.           PUSH   AX                    ; Synonym length_test_string
  129.           MOV    BP,SP                 ; Establish variables on stack
  130.  
  131.           MOV    AH,30H                ; get DOS version
  132.           doscall
  133.           CMP    AL,MIN_DOS            ; Is major version too early?
  134.           JL     wrong_DOS             ; Yes
  135.           CMP    AL,MAX_DOS            ; Is major version too late?
  136.           JLE    DOS_ok                ; No
  137.  
  138. wrong_DOS:
  139.           ADD    SP,original_stack_junk
  140.                                        ; Clear unneeded words from stack
  141.           MOV    AX,-1                 ; Error indicator
  142.           STC                          ; Set carry flag
  143.           JMP    is_resident_exit
  144.  
  145. DOS_ok:
  146.  
  147. ;              Call function 52 first, because it is undocumented, so may have
  148. ;         some side effects.
  149.           PUSH   DS                    ; DS for calling program
  150.           PUSH   ES                    ; Segment of PSP for calling program
  151.           MOV    AH,52H                ; Find segment of first block header
  152.           doscall
  153.           MOV    AX,ES:[BX-2]          ; Segment of first block header
  154.           POP    ES                    ; Restore segment registers
  155.           POP    DS                    ;
  156.           PUSH   AX                    ; Segment of first block header
  157.  
  158.           MOV    DX,DS                 ; DS for calling program
  159.           MOV    CX,ES                 ; Segment of PSP, which is the first
  160.                                        ; paragraph which DOS allocates for
  161.                                        ; a program
  162.           DEC    CX                    ; Segment of block header for calling
  163.                                        ; program
  164.           SUB    DX,CX                 ; Number of paragraphs from block
  165.                                        ; header to DS
  166.  
  167.           MOV    AX,WORD PTR [SI]      ; Signature => AX
  168.           MOV    WORD PTR [DI],AX      ; Signature to start of test string.
  169.                                        ; This distinguishes a copy which has
  170.                                        ; been run from a tramp copy in RAM.
  171.  
  172.           POP    ES                    ; Segment of first block header
  173.  
  174. check_last_block:
  175.           CMP    BYTE PTR ES:[0],'M'   ; Is there another block in the chain?
  176.           JNZ    check_destruction     ; No
  177.           TEST   ES:[1],0FFFFH         ; Is the current block unallocated
  178.           JZ     get_next_block        ; Yes, so don't check it
  179.           CMP    DX,WORD PTR ES:[3]    ; Is the current block big enough to
  180.                                        ; match?
  181.           JG     get_next_block        ; No
  182.           MOV    BX,ES                 ; Segment of block header
  183.           CMP    BX,CX                 ; Segment of block header for calling
  184.                                        ; program
  185.           JZ     get_next_block        ; Don't compare a block to itself
  186.           ADD    BX,DX                 ; Number of paragraphs from block
  187.                                        ; header to DS
  188.           MOV    DS,BX                 ; Set new DS
  189.           CMP    AX,WORD PTR [SI]      ; Does this segment contain the
  190.                                        ; signature?
  191.           JE     signatures_match      ; Yes.  Compare test strings
  192. get_next_block:
  193.           MOV    BX,ES                 ; Current block header
  194.           INC    BX                    ; Current block segment
  195.           ADD    BX,ES:[3]             ; Number of paragraphs in current
  196.                                        ; block
  197.           MOV    ES,BX                 ; Next block header
  198.           JMP    SHORT check_last_block ; And check again
  199.  
  200. signatures_match:
  201.           PUSH   ES                    ; Current block header
  202.           PUSH   CX                    ; Segment of block header for calling
  203.                                        ; program
  204.           PUSH   SI                    ; OFFSET of signature
  205.           PUSH   DI                    ; OFFSET of test string
  206.           MOV    SI,DI                 ; OFFSET of test string => SI
  207.           MOV    ES,old_DS             ; DS of calling program
  208.           MOV    CX,length_test_string ; Number of characters in test string
  209.           REPE   CMPSB                 ; Are the test strings equal?
  210.           POP    DI                    ; Restore OFFSET of test string
  211.           POP    SI                    ; Restore OFFSET of signature
  212.           POP    CX                    ; Restore segment of block header for
  213.                                        ; calling program
  214.           POP    ES                    ; Restore current block header
  215.           JZ     already_installed     ; Equal test strings
  216.           JMP    SHORT get_next_block  
  217.                                        ; Check again if still possible
  218. check_destruction:
  219.           CMP    BYTE PTR ES:[0],'Z'   ; Is this the last block in the chain?
  220.           JZ     first_copy            ; Yes
  221.           MOV    AX,-2                 ; Memory allocation error indicator
  222.           ADD    SP,original_stack_junk         
  223.                                        ; Move stack pointer up
  224.           STC                          ; Set carry flag
  225.           JMP    SHORT is_resident_exit
  226.  
  227. ;         No earlier resident copy.
  228. first_copy:
  229.           MOV    DS,old_DS             ; DS of calling program
  230.           XOR    AX,AX                 ; Show no copy is resident
  231.           ADD    SP,original_stack_junk         
  232.                                        ; Move stack pointer up
  233.           CLC                          ; Clear carry flag
  234.           JMP    SHORT is_resident_exit
  235.  
  236. already_installed:
  237.           MOV    AX,1                  ; Show a copy is resident
  238.           ADD    SP,original_stack_junk         
  239.                                        ; Move stack pointer up
  240.           STC                          ; Set carry flag          
  241.  
  242. is_resident_exit:
  243.           POP    ES                    ; Restore uninitialized registers
  244.           POP    BP
  245.           POP    DX
  246.           POP    CX          
  247.           POP    BX
  248.           RET
  249.  
  250. is_resident ENDP
  251.  
  252. ;-----------------------------------------------------------------------------
  253. ; OVERALL END
  254. ;-----------------------------------------------------------------------------
  255. COMSEG    ENDS
  256.           END
  257.  
  258.  
  259.